import base64
import hmac
import urllib

from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from myapp.myser import UserSer
from mydjango.settings import UPLOAD_ROOT, qiniu_AK, qiniu_SK
from mydjango.settings import Base_Url_Vue

import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

#使用装饰器联合JWT进行token验证
def My_Decotator(func):
    def warpper(request,*args,**kwargs):
        #判断JWT逻辑
        uid = request.GET.get('uid')
        client_jwt = request.GET.get("jwt",'null')
        #进行解密，比对uid是否一致
        try:
            decode_jwt = jwt.decode(client_jwt,'0722',algorithms=['HS256'])
            if str(decode_jwt['uid']) != str(uid):
                return HttpResponse('你涉嫌篡改用户ID，后台已记录！')
        except:
            return HttpResponse("你涉嫌篡改用户ID，后台已记录!")

        return func(request,*args,**kwargs)
    #返回内层函数的引用
    return warpper

from django.utils.decorators import method_decorator
#用户信息类
class UserInfo(APIView):
    @method_decorator(My_Decotator)
    def get(self,request):
        uid = request.GET.get("uid")
        #查询数据
        user = User.objects.get(id = int(uid))
        #序列化对象
        user_ser = UserSer(user)
        return Response(user_ser.data)

#更新用户头像
class UpdateUserImg(APIView):
    @method_decorator(My_Decotator)
    def get(self,request):
        #获取数据
        img = request.GET.get('img')
        username = request.GET.get("username")

        user = User.objects.filter(username=username).first()
        if user:
            #修改头图
            user.img = img
            user.save()
            result={}
            result['code']=200
            result['message'] = '修改用户头像成功'
            return Response(result)
        else:
            result={}
            result["code"] = 405
            result['message'] = '未知错误'
            return Response(result)

#定义七牛云存储接口
from qiniu import Auth
class Qiniu(APIView):
    def get(self,request):
        #定义密钥
        q = Auth(qiniu_AK,qiniu_SK)
        #指定上传空间mdmd2020
        token = q.upload_token('mdmd2020')
        print(token)
        res = {}
        res['token'] = token
        #只给前端返回一个token
        return Response(res)


#修改密码
class UserModify(APIView):
    def get(self,request):
        username = request.GET.get("username",'null')
        password = request.GET.get("password",'null')

        user = User.objects.filter(username=username).first()
        if user.password == make_Password(password):
            resp = {}
            resp["code"] = 405
            resp["message"] = '密码与先前密码一致！！'
            return Response(resp)
        else:
            user.password = make_Password(password)
            user.save()
            resp = {}
            resp["code"] = 200
            resp["message"] = '修改密码成功！'
            return Response(resp)

#定义上传视图类
class Upload_File(View):
    def post(self,request):
        #接受参数
        img = request.FILES.get('file')
        #建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT,'',(img.name).replace('"',"")),'wb')
        #写入
        for chunk in img.chunks():
            f.write(chunk)
        #关闭文件
        f.close()

        #添加水印
        # 思路：用画笔打开 图片，再将水印画到图片上
        #很奇怪为什么相对路径打不开
        image = Image.open('D:\\workspace\\www\\mydjango_zuoye\\static\\upload\\'+img.name)
        # print(image.size)
        # 生成画笔对象
        draw = ImageDraw.Draw(image)
        # 定义字体
        myfont = ImageFont.truetype(font='C:\\Windows\\Fonts\\STCAIYUN.TTF')
        # 修改
        draw.text((150, 150), '1906', fill=(176, 34, 224, 180), font=myfont)
        # 查看图片
        # 存储图片,直接覆盖了
        image.save('D:\\workspace\\www\\mydjango_zuoye\\static\\upload\\'+img.name)
        # 查看图片
        # image.show()

        #返回文件名
        return HttpResponse(json.dumps({'filename':img.name},ensure_ascii=False),content_type='application/json')

#钉钉登录回调
def ding_back(request):
    #获取授权码code&返回的state
    code = request.GET.get("code",'null')
    state = request.GET.get("state",'null')


    #钉钉开放平台提供的
    appId = 'dingoajtt4hfxbsp1tpdyv'
    appSecret = 'R7krrBZnXzoRGrHaJR9dhaYb_qgTOtq86dpreWThg60tiHfoenzCyZ6zNOmxb-9Y'
    #构建时间戳(单位毫秒)
    now_milli_time = str(int(time.time() * 1000))
    #构建签名
    signature = base64.b64encode(
        hmac.new(
            appSecret.encode('utf-8'),
            now_milli_time.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()).decode("utf-8")
    #通过临时授权码获取用户个人信息
    #post参数需要json类型
    #url签名参数写进url，data参数使用json
    res = requests.post(url='https://oapi.dingtalk.com/sns/getuserinfo_bycode?accessKey='
                            +appId+'&timestamp='+now_milli_time+'&signature='+urllib.parse.quote(signature),
        data=json.dumps({
            "tmp_auth_code": code
        }),
        headers={
            'Content-Type': 'application/json'
        }
    )

    #转码，获取用户名
    res = json.loads(res.text)
    name = res['user_info']['nick']

    # 判断是否使用过钉钉登录
    user = User.objects.filter(username=name).first()
    ding_id = ''
    user_id = ''
    if user:
        # 表示已经使用过微博登录并且成功注册到了数据库
        ding_id = user.username
        user_id = user.id
    else:
        # 首次登录，需要存储到数据库
        user = User(username=name, password='', type=0)
        user.save()

        # 查询用户ID
        user = User.objects.filter(username=name).first()
        ding_id = ding_id
        user_id = user.id

        encode_jwt = jwt.encode({'uid': str(user.id)}, '0722', algorithm='HS256')
        encode_strding = str(encode_jwt, 'utf-8')

    return redirect(Base_Url_Vue+'?ding_id='+str(ding_id)+'&uid='+str(user_id)+ '&jwt='+ encode_strding)

#微博 登录回调

def wb_back(request):
    #获取code
    code = request.GET.get("code")
    #定义微博认证地址获取token
    access_token_url = 'https://api.weibo.com/oauth2/access_token'
    #定义参数
    res = requests.post(
        url=access_token_url,
        data={
          'client_id':'2852114568',
          'client_secret':'fc391b9cf804f40d1309fd2f1e014abd',
          'grant_type':'authorization_code',
          'code':code,
          'redirect_uri':'http://127.0.0.1:8000/md_admin/weibo',
        }
    )

    res = json.loads(res.text)
    wbuid = res['uid']

    # 判断是否使用过sina微博登录
    user = User.objects.filter(username=wbuid).first()
    sina_id = ''
    user_id = ''
    if user:
        # 表示已经使用过微博登录并且成功注册到了数据库
        sina_id = user.username
        user_id = user.id
    else:
        # 首次登录，需要存储到数据库
        user = User(username=wbuid, password='', type=0)
        user.save()

    # 查询用户ID
    user = User.objects.filter(username=wbuid).first()
    sina_id = wbuid
    user_id = user.id

    encode_jwt = jwt.encode({'uid': str(user.id)}, '0722', algorithm='HS256')
    encode_str = str(encode_jwt, 'utf-8')

    return redirect(Base_Url_Vue+'?sina_id=' + str(sina_id) + "&uid=" + str(user_id)+'&jwt='+encode_str)


#登录逻辑
class Login(APIView):
    def get(self,request):
        #接受参数
        username = request.GET.get("username",'null')
        password = request.GET.get("password",'null')

        #查询数据库
        user = User.objects.filter(username=username,password=make_Password(password)).first()
        if user:
            res = {}
            res['code']=200
            res["message"]='登录成功'
            res['username'] = user.username
            res['uid'] = user.id
            # 加入jwt令牌机制
            # 进行编码
            encode_jwt = jwt.encode({'uid': str(user.id)}, '0722', algorithm='HS256')
            encode_str = str(encode_jwt, 'utf-8')
            res['jwt'] = encode_str
            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res["message"] = '用户名或密码错误'
            return Response(res)

#中文验证码
class Mycode(View):
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R,G,B)

    def get(self,request):
        #画布
        img_size = (150,50)
        #定义画图对象
        image = Image.new('RGB',img_size,'white')
        #定义画笔对象
        draw = ImageDraw.Draw(image,'RGB')
        #定义随机字符串
        source = '你好繁星向上没问题什么都不重复刚好就几个字'
        #定义容器
        code_str = ''
        #定义字体
        myfont = ImageFont.truetype(font='C:\\Windows\\Fonts\\FZSTK.TTF',size=30)
        for i in range(4):
            #获取随机颜色
            test_color = self.get_random_color()
            #获取字符串长度
            tep_num = random.randrange(len(source))
            #获取字符集
            random_str = source[tep_num]
            #添加到容器
            code_str += random_str
            #将字符添加到画布
            draw.text((10+30*i,10),random_str,test_color,font=myfont)

        #文件放入缓冲区
        buf = io.BytesIO()
        #后缀png
        image.save(buf,'png')

        request.session["code"] = code_str
        return HttpResponse(buf.getvalue(),'image/png')




#注册
class Register(APIView):
    def get(self,request):
        #获取用户名密码(get方法使用params传参）
        username = request.GET.get("username")
        password = request.GET.get("password")
        code = request.GET.get("code")

        #打印查看接收数据
        print(username)
        print(password)
        print(code)
        s_code = request.session.get('code','null')
        print(s_code)
        if code != s_code:
            resp = {'code': 405, "message": "验证码错误！"}
            return Response(resp)

        #对用户名进行查重
        user = User.objects.filter(username=username).first()

        if user:
            resp={'code':405,"message":"用户名已存在！"}
            return Response(resp)
        else:
            #存储的时候使用密码加密
            user = User(username=username,password=make_Password(password))
            user.save()
            resp={'code':200,"message":'恭喜您，注册成功！'}
            return Response(resp)


#md5加密逻辑
def make_Password(mypass):
    #md5对象
    md5 = hashlib.md5()
    #进行强转
    mysign_str = str(mypass)
    #转码
    mysign_code = mysign_str.encode(encoding='utf-8')
    #加密
    md5.update(mysign_code)
    #生成密钥串
    md5_server = md5.hexdigest()

    return md5_server


#方法视图
def myindex(request):

    return HttpResponse('这里是首页')

#类视图
class MyView(View):
    def get(self,request):
        user = User.objects.all()

        return render(request,'index.html',context={'user':user})
